class MyPromise {
    static PENDING = 'pending'
    static FULFILLEd = 'fulfilled'
    static REJECTED = 'rejected'
    constructor(initFun) {
        this.status = MyPromise.PENDING
        this.resolveCallbacks = []
        this.rejectCallbacks = []
        this.res = null
        this.err = null
        const resolve = (res) => {
            if (this.status === MyPromise.PENDING) {
                this.status = MyPromise.FULFILLEd
                this.res = res
                this.resolveCallbacks.forEach(fn => fn())
            }
        }
        const reject = (err) => {
            if (this.status === MyPromise.PENDING) {
                this.status = MyPromise.REJECTED
                this.err = err
                this.rejectCallbacks.forEach(fn => fn())
            }
        }

        if (initFun) {
            try {
                initFun(resolve, reject)  // 注意this指向
            } catch (err){
                reject(err)
            }
        }
    }
    then(onFulfilled, onRejected) {
        // const { res, err } =this
        return new MyPromise((resolve, reject) => {
            const onFulfilledCallback = (res) => {
                try {
                    if (typeof onFulfilled !== 'function') {
                        resolve(res)
                    } else {
                        const thenRes = onFulfilled(res)
                        if (thenRes instanceof MyPromise) {
                            thenRes.then(resolve, reject)
                        } else {
                            resolve(thenRes)
                        }
                    }
                } catch (err) {
                    reject(err)
                }
            }
            const onRejectedCallback = (res) => {
                try {
                    if (typeof onFulfilled !== 'function') {
                        reject(res)
                    } else {
                        const thenRes = onRejected(res)
                        if (thenRes instanceof MyPromise) {
                            thenRes.then(resolve, reject)
                        } else {
                            reject(thenRes)
                        }
                    }
                } catch (err) {
                    reject(err)
                }
            }

            if (this.status === MyPromise.resolveStatus) {
                onFulfilledCallback(this.res)
            } else if (this.status === MyPromise.rejectStatus) {
                onRejectedCallback(this.err)
            } else if (this.status === MyPromise.pendingStatus) {
                if (onFulfilled && typeof onFulfilled === 'function') {
                    this.resolveCallbacks.push(() => {
                        setTimeout(() => {
                            onFulfilledCallback(this.res)
                        }, 0)
                    })
                }
                if (onRejected && typeof onRejected === 'function') {
                    this.rejectCallbacks.push(() => {
                        setTimeout(() => {
                            onRejectedCallback(this.err)
                        }, 0)
                    })
                }
            }
        })
    }
    static resolve(data) {
        //1.参数是一个Promise实例,直接返回
        if (data instanceof MyPromise) {
            return data
        }
        //2.参数是一个thenable对象，转为Promise后执行该对象的then方法
        if (typeof data === 'object' && typeof data.then === 'function') {
            return new MyPromise((resolve, reject) => {
                data.then(resolve, reject)
            })
        }
        //3.没有参数，直接返回一个resolved状态的promise
        if (!data) {
            return new MyPromise((resolve) => {
                resolve()
            })
        }
         //4.参数是一个原始值，返回一个新的Promise，状态为resolved
        return new MyPromise((resolve) => {
            resolve(data)
        })
    }
    static reject(err) {
        return new MyPromise((_, reject) => reject(err))
    }

    // 所有的promises都成功才resolve,只要有一个报错就reject。
    static all(promises) {
        return new MyPromise((resolve, reject) => {
            const result = []
            const count = 0;
            function addResult(res, idx) {
                result[idx] = res
                count++
                if (result.length === count) {
                    resolve(result)
                }
            }
            [].forEach.call(promises, (promise, idx) => {
                if (promise instanceof MyPromise) {
                    promise.then(res => {
                        addResult(res, idx)
                    }).catch(err => {
                        reject(err)
                    })
                } else {
                    addResult(promise, idx)
                }
            })
        })
    }

    // promises中只要有一个有返回结果，无论是成功还是失败都结束。
    static race(promises) {
        return new MyPromise((resolve, reject) => {
            [].forEach.call(promises, (promise, idx) => {
                if (promise instanceof MyPromise) {
                    promise.then(res => {
                        resolve(res)
                    }).catch(err => {
                        reject(err)
                    })
                } else {
                    resolve(promise)
                }
            })
        })
    }

    // 必须所有的promise都有结果（无论结果是成功还是失败）了才会结束
    static allSettled(promises) {
        return new MyPromise((resolve, reject) => {
            const result = []
            const count = 0;
            function addResult(res, idx) {
                result[idx] = res
                count++
                if (result.length === count) {
                    resolve(result)
                }
            }
            [].forEach.call(promises, (promise, idx) => {
                if (promise instanceof MyPromise) {
                    promise.then(res => {
                        addResult({
                            status: 'fulfilled', value: res
                        }, idx)
                    }).catch(err => {
                        addResult({
                            status: 'rejected', reason: err
                        }, idx)
                    })
                } else {
                    addResult(promise, idx)
                }
            })
        })
    }

    // Promise.any()跟Promise.race()方法很像，只有一点不同，就是Promise.any()不会因为某个 Promise 变成rejected状态而结束，必须等到所有参数 Promise 变成rejected状态才会结束
    // promises必须全部reject才会变成rejected状态结束，只要有一个成功，就fulfilled
    static any(promises) {
        return new MyPromise((resolve, reject) => {
            const result = []
            const count = 0;
            function addReject(res, idx) {
                result[idx] = res
                count++
                if (result.length === count) {
                    reject(result)
                }
            }
            [].forEach.call(promises, (promise, idx) => {
                if (promise instanceof MyPromise) {
                    promise.then(res => {
                        resolve(res)
                    }).catch(err => {
                        addReject(err, idx)
                    })
                } else {
                    resolve(promise)
                }
            })
        })
    }
}

Promise.resolve()
  .then(() => {
    console.log(0);
    // return Promise.resolve(4);
    const promise = new Promise((resovle) => {
        console.log(3)
        resovle(4)
    })
    return promise
  })
  .then((res) => {
    console.log(res);
  });

Promise.resolve()
  .then(() => {
    console.log(1);
  })
  .then(() => {
    console.log(2);
  })
  .then(() => {
    console.log(3);
  })
  .then(() => {
    console.log(5);
  })
  .then(() => {
    console.log(6);
  });


// 题目二,求以下代码输出顺序
setTimeout(() => {
    console.log(1)
})
const p = new Promise((resolve,reject) => {
    console.log(2)
    resolve(3) //1.改变了当前promise状态，但是还没有执行到then,所以then的onFufilled方法还没有进入微队列
    //2.Promise.resolve(4)改变了promise状态后立即调用了then的方法，所以then的onFufilled方法此时进入了微队列
    Promise.resolve(4).then(console.log)
    console.log(5)
    //3.调用了then的方法，所以then的onFullfilled方法此时进入了微队列
}).then(console.log)
console.log(6)

// 宏队列：console.log(1) 微队列：console.log(4)，console.log(3)
// 同步执行2、5、6
// 执行微队列：console.log(4)，console.log(3) 结果=2、5、6、4、3
// 执行宏队列：console.log(1) 结果=2、5、6、4、3、1
// 答案2、5、6、4、3、1

// Promise的onFulfilled什么时候进入微队列
// 1.resolve时，如果有注册的onFulfilled，进入微队列
// 2.调用then方法时如果此时Promise已经完成，其回调进入微队列

new Promise(resolve => {
    // 一秒后执行resolve
  setTimeout(() => {
    // 当resolve时，then已经有注册的onFulfilled，此时直接将then回调进入微队列
    resolve(1)
  }, 1000)
}).then(console.log)